# -*- coding: utf-8 -*-

'''
任务管理函数
'''
from ...pao_python.pao.data import process_db, dataframe_to_list, DataProcess, DataList
import pandas as pd
import uuid
import datetime
import re
import hashlib
from enum import Enum
from ...service.mongo_bill_service import MongoBillFilter
from ...pao_python.pao.service.security.security_service import RoleService
from ...pao_python.pao.service.security.security_utility import get_current_account_id
from ...service.common import insert_data, find_data, update_data, delete_data, get_condition, get_info
from ...service.buss_pub.bill_manage import BillManageService, OperationType, TypeId, Status
from server.pao_python.pao.service.data.mongo_db import MongoService, MongoFilter, C, N, F, as_date
from ..buss_pub.personnel_organizational import UserType
from server.pao_python.pao.data import process_db, get_cur_time
from ...service.common import get_current_user_id, get_current_role_id
from ...service.app.my_order import RecordStatus


class TaskState(Enum):
    '''任务状态类型枚举'''
    To_be_processed = '待处理'
    Failed_examine = '审核未通过'
    Adopt_examine = '审核通过'
    To_be_receive = '待接收'
    Ongoing = '进行中'
    Rejected = '已拒绝'
    Completed = '已完成'
    Evaluated = '已评价'


class UrgentLevel(Enum):
    '''紧急程度枚举
    '''
    Urgent = '紧急'
    Normal = '一般'


class TaskManageService(MongoService):
    ''' 任务管理 '''
    Task = 'PT_Task'
    Task_type = 'PT_Task_Type'

    def __init__(self, db_addr, db_port, db_name, db_user, db_pwd, inital_password, session):
        self.db_addr = db_addr
        self.db_port = db_port
        self.db_name = db_name
        self.db_user = db_user
        self.db_pwd = db_pwd
        self.inital_password = inital_password
        self.session = session
        self.bill_manage_server = BillManageService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)

    def update_task_type(self, data):
        '''新增或者修改任务类型数据'''
        res = 'Fail'
        if 'id' in list(data.keys()):
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.taskType.value, data, self.Task_type)
            if bill_id:
                res = 'Success'
        else:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.taskType.value, data, self.Task_type)
            if bill_id:
                res = 'Success'
        return res

    def get_task_type_list(self, org_list, condition, page, count):
        '''获取任务类型列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        keys = ['id', 'name']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id'])
                           & (C('name').like(values['name']))
                           & (C('organization_id').inner(org_list)))\
            .project({'_id': 0})
        res = self.page_query(_filter, self.Task_type, page, count)
        return res

    def input_task_type(self):
        '''任务类型下拉框数据'''
        _filter = MongoBillFilter()
        _filter.match_bill()\
               .project({'_id': 0})
        res = self.query(_filter, self.Task_type)
        return res

    def input_task_urgent(self):
        '''任务紧急程度下拉框数据'''
        res = []
        for i in UrgentLevel:
            res.append(i.value)
        return res

    def input_person(self):
        '''人员姓名下拉框数据'''
        _filter = MongoBillFilter()
        _filter.match_bill(C('personnel_type') == UserType.Personnel)\
               .project({'_id': 0, 'id': 1, 'name': 1})
        res = self.query(_filter, 'PT_User')
        return res

    def add_new_task(self, data, state):
        '''增加新任务（两种状态，一种为待接收，一种为待处理
        Arguments：
            data {dict} 任务数据，包含关键字：send_user_id(发送任务人的id)
        '''
        res = 'Fail'
        if state == TaskState.To_be_receive.value:
            operation = '接收任务'
        else:
            operation = '创建任务'
        data = self.__add_process_record(data, operation)  # 增加过程记录
        data['task_state'] = state  # 增加状态，待处理
        # 创建任务的人
        data['task_creator'] = get_current_user_id(self.session)
        bill_id = self.bill_manage_server.add_bill(
            OperationType.add.value, TypeId.task.value, data, self.Task)
        if bill_id:
            res = 'Success'
        return res

    def __add_process_record(self, data, operation):
        date = datetime.datetime.now()
        # 该字段在审核不通过和拒绝接收任务时出现，需添加在过程记录字段中
        reason = data.pop('task_fail_reason', None)
        i_record = {'id': str(uuid.uuid1()), 'user_id': get_current_user_id(self.session),
                    'user_operate': operation, 'date': date, 'record_message': reason}
        if 'id' in data:
            _filter = MongoBillFilter()
            _filter.match_bill(C('id') == data['id'])
            res = self.query(_filter, self.Task)
            if len(res) > 0:
                # 没有的话，就给个空的，防止报错
                if 'task_process_record' not in res[0]:
                    res[0]['task_process_record'] = []

                task_process_record = res[0]['task_process_record']
                task_process_record.append(i_record)
                data['task_process_record'] = task_process_record
            else:
                return 'Fail'
        else:
            data['task_process_record'] = [i_record]
        return data

    def task_examine(self, data, examine_res):
        '''任务审核,
        Arges:
        data : {'ids':['','',''],'task_fail_reason':''}
        examine_res : 为true时即为通过，为false时即为不通过
        '''
        res = 'Fail'
        bill_id_list = []
        examine_list = []
        for i in data['ids']:
            examine_data = {'id': i}
            if examine_res == False:
                examine_data['task_fail_reason'] = data['task_fail_reason']
            examine_list.append(
                self.__add_process_record(examine_data, '审核任务'))

        for examine_item in examine_list:
            if examine_item != 'Fail':
                if examine_res:
                    examine_item['task_state'] = TaskState.Adopt_examine.value
                else:
                    examine_item['task_state'] = TaskState.Failed_examine.value
                bill_id_list.append(self.bill_manage_server.add_bill(
                    OperationType.update.value, TypeId.task.value, examine_item, self.Task))
        if False not in bill_id_list:
            res = 'Success'
        return res

    def task_receive(self, data, receive_res):
        '''接收任务,receive_res为true时即为接受任务，为false时即为拒绝任务'''
        res = 'Fail'
        data = self.__add_process_record(data, '接收任务')
        if data != 'Fail':
            if receive_res:
                data['task_state'] = TaskState.Ongoing.value
            else:
                data['task_state'] = TaskState.Rejected.value
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.task.value, data, self.Task)
            if bill_id:
                res = 'Success'
        return res

    def task_appoint(self, data):
        '''
        指派任务
        Arges:
        data : {'ids':['','',''],'task_receive_person':''}
        '''
        res = 'Fail'
        bill_id_list = []
        appoint_list = []
        for i in data['ids']:
            receive_data = {
                'id': i, 'task_receive_person': data['task_receive_person']}
            appoint_list.append(
                self.__add_process_record(receive_data, '指派任务'))

        for appoint_item in appoint_list:
            if appoint_item != 'Fail':
                appoint_item['task_state'] = TaskState.To_be_receive.value
                bill_id_list.append(self.bill_manage_server.add_bill(
                    OperationType.update.value, TypeId.task.value, appoint_item, self.Task))
        if False not in bill_id_list:
            res = 'Success'
        return res

    def task_complete(self, data):
        '''完成任务'''
        res = 'Fail'
        data = self.__add_process_record(data, '完成任务')
        if data != 'Fail':
            data['task_state'] = TaskState.Completed.value
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.task.value, data, self.Task)
            if bill_id:
                res = 'Success'
        return res

    def change_task_service_order(self, data):
        '''服务订单分派的任务完成判断逻辑'''
        res = 'Fail'

        # 根据数据本体状态和传入的内容决定状态
        # 如果传了开始内容没有结束内容，那就表示进行中
        # 如果都传了，那就表示是完成了
        EMPTY_DATA = '没有找到该数据'
        INVALID_DATA = '非法操作'
        MISSION_PRO = '完成任务'
        TASK_STATE = TaskState.Completed.value
        record_data = {}

        # 订单ID
        if 'order_id' not in data:
            return '没有订单ID'
            
        order_id = data['order_id']
        del(data['order_id'])

        # 防止有问题
        if data['start_date'] != '':
            start_date = data['start_date'][0:10] + \
                ' '+data['start_date'][12:19]
            data['start_date'] = datetime.datetime.strptime(
                start_date, '%Y-%m-%d %H:%M:%S')
        else:
            data['start_date'] = get_cur_time()
        if data['end_date'] != '':
            end_date = data['end_date'][0:10] + \
                ' '+data['end_date'][12:19]
            data['end_date'] = datetime.datetime.strptime(
                end_date, '%Y-%m-%d %H:%M:%S')
        else:
            data['end_date'] = get_cur_time()

        if 'id' not in data:
            return EMPTY_DATA
        else:
            _fillter = MongoBillFilter()
            _fillter.match_bill(C('id') == data['id'])\
                .project({'_id': 0})
            data_result = self.query(_fillter, 'PT_Task')

            if len(data_result) == 0:
                return EMPTY_DATA

            # 本体是待接收的状态
            if data_result[0]['task_state'] == TaskState.To_be_receive.value:
                # 没有必传数据
                if data['begin_photo'] == '':
                    return INVALID_DATA
                # 有结束数据，就表示完成了
                if data['end_photo'] != '':
                    MISSION_PRO = '完成任务'
                    ORDER_PRO = '已完成'
                    TASK_STATE = TaskState.Completed.value
                    # 记录表的数据
                    record_data['start_date'] = data['start_date']
                    record_data['end_date'] = data['end_date']
                    record_data['status'] = RecordStatus.service_completed.value
                else:
                    MISSION_PRO = '接收任务'
                    ORDER_PRO = '服务中'
                    TASK_STATE = TaskState.Ongoing.value
                    # 记录表的数据
                    record_data['start_date'] = data['start_date']
                    record_data['status'] = RecordStatus.service_going.value
            elif data_result[0]['task_state'] == TaskState.Ongoing.value:
                # 禁止再传开始数据
                if 'begin_photo' in data:
                    del(data['start_date'])
                    del(data['begin_photo'])
                # 没有必传数据
                if data['end_photo'] == '':
                    return INVALID_DATA

                MISSION_PRO = '完成任务'
                ORDER_PRO = '已完成'
                TASK_STATE = TaskState.Completed.value
                # 记录表的数据
                record_data['end_date'] = data['end_date']
                record_data['status'] = RecordStatus.service_completed.value

        data = self.__add_process_record(data, MISSION_PRO)
        if data != 'Fail':
            data['task_state'] = TASK_STATE
            # 补充服务记录表的主键
            record_data['id'] = data_result[0]['task_object_id']

            # 要做两个操作，一个是服务记录要改状态，一个是任务表要改状态
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.task.value, [record_data, {'id' : order_id, 'status' : ORDER_PRO}, data], ['PT_Service_Record', 'PT_Service_Order', self.Task])
            if bill_id:
                res = 'Success'
        return res

    def get_record_list(self, condition):
        keys = ['id', 'user_operate']
        values = self.get_value(condition, keys)
        if isinstance(values['id'], str):
            values['id'] = [values['id']]
        _filter = MongoBillFilter()
        _filter.match_bill(C('id').inner(values['id']))\
               .unwind('task_process_record')\
               .match(C('user_operate').like(values['user_operate']))\
               .inner_join_bill('PT_User', 'task_process_record.user_id', 'id', 'user_info')\
               .project({'_id': 0, 'task_name': 1, 'task_content': 1,
                         'user_name': '$user_info.name',
                         'user_operate': '$task_process_record.user_operate',
                         'record_message': '$task_process_record.record_message',
                         'date': '$task_process_record.date'})
        res = self.query(_filter, self.Task)
        return res

    def get_all_task_list(self, org_list, condition, page, count):
        '''获取任务列表
        Arguments:
            condition   {dict}      条件,其中task_state为列表格式
            page        {number}    页码
            count       {number}    条数
        '''

        keys = ['id', 'task_content', 'task_name', 'task_urgent',
                'task_type', 'task_state', 'task_receive_person']

        if 'task_type' in condition and condition['task_type'] == '服务分派':
            _filter_task_type = MongoBillFilter()
            _filter_task_type.match_bill(C('name') == '服务分派')\
                .project({'_id': 0})
            task_type_res = self.query(_filter_task_type, 'PT_Task_Type')

            if len(task_type_res) > 0:
                condition['task_type'] = task_type_res[0]['id']

        values = self.get_value(condition, keys)
        if isinstance(values['task_state'], str):
            values['task_state'] = [values['task_state']]

        _filter = MongoBillFilter()
        _filter.match_bill((C('task_state').inner(values['task_state']))
                           & (C('id') == values['id'])
                           & (C('task_type') == values['task_type'])
                           & (C('task_urgent') == values['task_urgent'])
                           & (C('task_content').like(values['task_content']))
                           & (C('task_name').like(values['task_name']))
                           & (C('task_receive_person') == values['task_receive_person'])
                           & (C('organization_id').inner(org_list)))

        if 'user_filter' in list(condition.keys()) and get_current_role_id(self.session) != '8f72e614-e355-11e9-a8b8-a0a4c57e9ebe':
            cur_user_id = get_current_user_id(self.session)
            _filter.match_bill(C('task_receive_person') == cur_user_id)

        _filter.lookup_bill('PT_User', 'purchaser_id', 'id', 'purchaser_info')\
            .lookup_bill('PT_User', 'organization_id', 'id', 'organization_info')\
            .lookup_bill('PT_Personnel_Classification', 'purchaser_info.personnel_info.personnel_classification', 'id', 'classification_info')\
            .lookup_bill(self.Task_type, 'task_type', 'id', 'task_type_info')\
            .unwind('task_type_info', True)\
            .lookup_bill('PT_User', 'task_receive_person', 'id', 'receiver_info')\
            .unwind('receiver_info', True)\
            .lookup_bill('PT_User', 'task_creator', 'id', 'creator_info')\
            .unwind('creator_info', True)\
            .add_fields({
                'task_type_name': '$task_type_info.name', 
                'receiver_info_name': '$receiver_info.name', 
                'task_creator_name': '$creator_info.name', 
                'purchaser_name': '$purchaser_info.name', 
                'purchaser_telephone': '$purchaser_info.personnel_info.telephone', 
                'classification_name': '$classification_info.name', 
                'organization_name' : '$organization_info.name'})\
            .project({'_id': 0, 'purchaser_info': 0, 'organization_info': 0, 'classification_info': 0, 'task_type_info._id': 0, 'receiver_info._id': 0, 'creator_info._id': 0})
        res = self.page_query(_filter, self.Task, page, count)
        return res

    def get_to_be_processed_task_list(self, org_list, condition, page, count):
        '''获取待处理(未进行过审核)的任务列表'''
        condition['task_state'] = [TaskState.To_be_processed.value]
        return self.get_all_task_list(org_list, condition, page, count)

    def get_to_be_send_task_list(self, org_list, condition, page, count):
        '''获取待派单的任务列表'''
        condition['task_state'] = [
            TaskState.Adopt_examine.value, TaskState.Rejected.value]
        return self.get_all_task_list(org_list, condition, page, count)

    def get_to_be_receive_task_list(self, org_list, condition, page, count):
        '''<app>获取待接收的任务列表
        '''
        condition['task_state'] = [TaskState.To_be_receive.value]
        return self.get_all_task_list(org_list, condition, page, count)

    def get_ongoing_task_list(self, org_list, condition, page, count):
        '''<app>获取进行中的任务列表
        '''
        condition['task_state'] = [TaskState.Ongoing.value]
        return self.get_all_task_list(org_list, condition, page, count)

    def get_completed_task_list(self, org_list, condition, page, count):
        '''<app>获取已完成的任务列表'''
        condition['task_state'] = [TaskState.Completed.value]
        return self.get_all_task_list(org_list, condition, page, count)

    def get_task_service_order_list(self, org_list, condition, page, count):
        '''<app>获取服务任务列表'''
        condition['task_type'] = '服务分派'
        return self.get_all_task_list(org_list, condition, page, count)
